home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-09-30 | 57.1 KB | 1,921 lines |
- Newsgroups: comp.sources.misc
- subject: v08i075: cz text to PostScript system, part 11 of 14
- from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Reply-To: howard@dahlbeck.ericsson.se (Howard Gayle)
-
- Posting-number: Volume 8, Issue 75
- Submitted-by: howard@dahlbeck.ericsson.se (Howard Gayle)
- Archive-name: cz/part11
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of archive 11 (of 14)."
- # Contents: cz0.c
- # Wrapped by howard@dahlbeck on Mon Sep 25 07:15:24 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'cz0.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cz0.c'\"
- else
- echo shar: Extracting \"'cz0.c'\" \(54952 characters\)
- sed "s/^X//" >'cz0.c' <<'END_OF_FILE'
- X/*
- X * cz0 - Convert text in any octet-based character set into PostScript.
- X */
- X
- X#include <stdio.h>
- X#include <howard/port.h>
- X#include <howard/version.h>
- X#include <howard/usage.h>
- X
- XMAINVER ("@(#)$Header: cz0.c,v 2.25 89/08/21 10:54:56 howard Exp $");
- XUSAGE ("[-o file] {-command argument}");
- X
- X#include <ctype.h>
- X#include <string.h>
- X#include <time.h>
- X#include <howard/a2.h>
- X#include <howard/malf.h>
- X#include <howard/registers.i>
- X#include "FREEZE.i"
- X#include "cz.h"
- X#include "ps-abbrev.i"
- X#include "cz0.h"
- X#include "state0.i"
- X
- X/* a2ocol - convert string to output column number */
- X
- XPRIVATE ushrtT a2ocol (s, n)
- XbStrT s; /* Input string.*/
- XbStrT n; /* Field name.*/
- X
- X/* Function:
- X * s is a string representation of an output column number, e.g.
- X * FoldFirst. It is either "Inf" for the maximum output column,
- X * or an integer numeric literal.
- X * Algorithm:
- X *
- X * Returns:
- X *
- X * Notes:
- X *
- X */
- X{
- Xreturn (bStrEQ (S("Inf"), s) ? MOCOL : ADA_US (s, n, 0, MOCOL));
- X}
- X
- X/* addFnt - add a font to fonts[] if it's not already there */
- X
- XPRIVATE void addFnt (f, s)
- XR2 bStrT f; /* Font name.*/
- X boolT s; /* A symbol font.*/
- X
- X/* Function:
- X * If font f is not already in the list of fonts used, add it.
- X * If it *is* already in the list, make sure its stored symbol font
- X * status is the same as s.
- X * Algorithm:
- X * Linear search.
- X * Returns:
- X *
- X * Notes:
- X * 1) It's necessary to distinguish symbol fonts from non-symbol
- X * fonts because symbol fonts must not be reencoded.
- X */
- X{
- XR1 fontT *fp; /* Steps through fonts[].*/
- X
- Xfor (fp = fonts; (fp != fontP) && !bStrEQ (f, fp->fntName); ++fp)
- X ;
- Xif (fp == fontP)
- X {
- X if (fp == &fonts[MFONTS]) malf1 (eMFonts, MFONTS);
- X fp->fntName = f;
- X fp->fntSymb = s;
- X ++fontP;
- X }
- Xelse if (fp->fntSymb != s)
- X malf1 (eSymFnt, f);
- X}
- X
- X/* addso - add one state-octet pair to state table */
- X
- XPRIVATE void addso (sos, pss)
- XR4 bStrT sos; /* State-octet pair as a string.*/
- XR5 bStrT pss; /* Corresponding PostScript string.*/
- X
- X/* Function:
- X * sos is a string representing a state-octet pair.
- X * pss is a string containing the text to emit for that pair,
- X * and optionally a new state at the end. addso() enters
- X * this into the state table, building new parts if necessary.
- X * Algorithm:
- X * Convert state and octet to numbers. Check pss for bad escapes.
- X * If there is no entry in state table for s, make one.
- X * If there is a next state at the end of pss, convert it to a number.
- X * Store pss and next state for this pair.
- X * Returns:
- X *
- X * Notes:
- X * 1) Should probably convert pss to nextc() output format here.
- X */
- X{
- XR6 unsigned ns = 0; /* Next state.*/
- XR7 unsigned o; /* Octet.*/
- XR1 bStrT p1; /* General purpose.*/
- XR8 unsigned s; /* State.*/
- XR2 soT *sop1; /* Current soT.*/
- XR3 soT *sop2; /* End of new stateT.*/
- XR9 stateT *sp; /* Points to current stateT.*/
- X
- Xp1 = bStrChr (sos, SOSEP);
- Xif (NULBSTR == p1) malf1 (eSOSep, SOSEP, sos, pss);
- Xs = mra2u (sos, p1, FALSE, S("State"), (unsigned) 0, (unsigned) MSTATE,
- X (bStrT *) NULL);
- Xo = mra2u (1 + p1, NULBSTR, FALSE, S("Octet"), (unsigned) 0, (unsigned) 255,
- X (bStrT *) NULL);
- Xfor (p1 = pss; NULBSTR != (p1 = bStrChr (p1, E_ESC)); ++p1)
- X {
- X ++p1;
- X if (T_RES == ncMap[B(*p1)]) malf1 (eEsc, E_ESC, B(*p1), sos, pss);
- X }
- Xsp = states[s];
- Xif (((stateT *) NULL) == sp)
- X {
- X sp = (stateT *) mcalloc (1, sizeof (stateT), "State table");
- X sop1 = (soT *) sp;
- X sop2 = sop1 + 256;
- X for (; sop1 != sop2; ++sop1)
- X sop1->so_ps = NULBSTR;
- X states[s] = sp;
- X }
- Xp1 = bStrRChr (pss, E_ESC);
- Xif ((NULBSTR != p1) && (E_NEXTS == B(p1[1])))
- X {
- X ns = mra2u (2 + p1, NULBSTR, FALSE, S("Next state"), (unsigned) 0,
- X (unsigned) MSTATE, (bStrT *) NULL);
- X *p1 = EOS;
- X }
- Xif (strlen (pss) > MPSSTR) malf1 (eBigPS, sos, MPSSTR, pss);
- Xsop1 = ((soT *) sp) + o;
- Xsop1->so_nxt = ns;
- Xsop1->so_ps = mcpstr (pss);
- Xif (DB(D_OCT))
- X FPRINTF (stderr, "State %u Octet %c 8#%o# (%s%c%c%u)\n",
- X s, o, o, sop1->so_ps, E_ESC, E_NEXTS, sop1->so_nxt);
- X}
- X
- X/* cmd - execute one command */
- X
- XPRIVATE void cmd (cp, ap, fn, ln)
- XR1 bStrT cp; /* Command.*/
- X bStrT ap; /* Argument.*/
- X cStrT fn; /* File name.*/
- X unsigned ln; /* Line number in file.*/
- X
- X/* Function:
- X * Execute the given command with the given argument. On error,
- X * write an error message, using the file name and line number.
- X * Algorithm:
- X * Linear search for command name.
- X * Notes:
- X * 1) Should use perfect hashing.
- X */
- X{
- XR2 bStrT p; /* General putpose.*/
- X
- Xif (DB(D_CMD)) FPRINTF (stderr, "%s: %u: %s %s\n", fn, ln, cp, ap);
- Xif (NULBSTR != (p = prefix (S("AutoColumn"), cp)))
- X param0.AutoCol[ADA_US (p, "Number of columns", 1, MPAGCOL)] =
- X a2ocol (ap, S("Maximum number of output columns"));
- Xelse if (bStrEQ (S("AutoFile"), cp))
- X param0.AutoFil = ms2bool (ap, cp);
- Xelse if (bStrEQ (S("AutoLandscape"), cp))
- X param0.AutoLnd = a2ocol (ap, cp);
- Xelse if (bStrEQ (S("BodySize"), cp))
- X param0.BodySiz = mra2bp (ap, cp, 1.0, 1000.0);
- Xelse if (bStrEQ (S("BottomMarginLandscape"), cp))
- X param0.BMargL = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("BottomMarginPortrait"), cp))
- X param0.BMargP = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("BottomSkip"), cp))
- X param0.BSkip = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("CommandFile"), cp))
- X {
- X if (bStrEQ (ap, S("-"))) readrc (stdin, sStdin); else readpth (ap);
- X }
- Xelse if (bStrEQ (S("Columns"), cp))
- X param0.Columns = ADA_US (ap, cp, 1, MPAGCOL);
- Xelse if (bStrEQ (S("ColumnSeparation"), cp))
- X param0.ColSep = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("Debug"), cp))
- X Debug = ADA_INT (ap, cp, 0, 9);
- Xelse if (bStrEQ (S("EndControlD"), cp))
- X EndCtlD = ms2bool (ap, cp);
- Xelse if (bStrEQ (S("FixedWidthBodyFont"), cp))
- X param0.FWFont = mcpstr (ap);
- Xelse if (bStrEQ (S("File"), cp))
- X {
- X if (filp == &fil[MFILES + 1]) malf1 (eMFiles, MFILES);
- X filp->filName = mcpstr (ap);
- X filp->filPara = param0;
- X ++filp;
- X }
- Xelse if (bStrEQ (S("FixedWidth"), cp))
- X param0.FixWid = ms2bool (ap, cp);
- Xelse if (bStrEQ (S("FoldFirst"), cp))
- X param0.FoldFst = a2ocol (ap, cp);
- Xelse if (bStrEQ (S("FoldIndent"), cp))
- X param0.FoldInd = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("FoldRest"), cp))
- X param0.FoldRst = a2ocol (ap, cp);
- Xelse if (bStrEQ (S("FooterFont"), cp))
- X param0.FootFnt = mcpstr (ap);
- Xelse if (bStrEQ (S("FooterHeight"), cp))
- X param0.FootHt = mra2bp (ap, cp, 0.0, 72.0);
- Xelse if (bStrEQ (S("Header"), cp))
- X filp->filHdr = mcpstr (ap);
- Xelse if (bStrEQ (S("HeaderFont"), cp))
- X param0.HeadFnt = mcpstr (ap);
- Xelse if (bStrEQ (S("HeaderHeight"), cp))
- X param0.HeadHt = mra2bp (ap, cp, 0.0, 1000.0);
- Xelse if (bStrEQ (S("LandscapeRotation"), cp))
- X {
- X param0.LandRot = ADA_INT (ap, cp, -90, 90);
- X if ((-90 != param0.LandRot) && (90 != param0.LandRot)) malf1 (eRot);
- X }
- Xelse if (bStrEQ (S("LeftMarginLandscape"), cp))
- X param0.LMargL = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("LeftMarginPortrait"), cp))
- X param0.LMargP = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("LineNumberFont"), cp))
- X param0.LNFnt = mcpstr (ap);
- Xelse if (bStrEQ (S("LineNumberHeight"), cp))
- X param0.LNHt = mra2bp (ap, cp, 0.0, 72.0);
- Xelse if (bStrEQ (S("LineNumberMultiple"), cp))
- X param0.LNMult = ADA_US (ap, cp, 0, 1000);
- Xelse if (bStrEQ (S("LineNumberWidth"), cp))
- X param0.LNWid = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (NULBSTR != (p = prefix (S("Octet"), cp)))
- X addso (p, ap);
- Xelse if (bStrEQ (S("PageHeight"), cp))
- X param0.PageHt = mra2bp (ap, cp, MM(100.0), MM(1000.0));
- Xelse if (bStrEQ (S("PageWidth"), cp))
- X param0.PageWid = mra2bp (ap, cp, MM(100.0), MM(1000.0));
- Xelse if (bStrEQ (S("PostScript"), cp))
- X FPRINTF (psos, "%s\n", ap);
- Xelse if (bStrEQ (S("Reverse"), cp))
- X Reverse = ms2bool (ap, cp);
- Xelse if (bStrEQ (S("RightMarginLandscape"), cp))
- X param0.RMargL = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("RightMarginPortrait"), cp))
- X param0.RMargP = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("Spacing"), cp))
- X param0.Spacing = mra2d (ap, NULBSTR, TRUE, cp, 0.5, 10.0, (bStrT *) NULL);
- Xelse if (bStrEQ (S("SymbolFont"), cp))
- X param0.SymbFnt = mcpstr (ap);
- Xelse if (bStrEQ (S("TabWidth"), cp))
- X param0.TabWid = ADA_US (ap, cp, 1, 80);
- Xelse if (bStrEQ (S("TextVertical"), cp))
- X param0.TxtVert = ms2bool (ap, cp);
- Xelse if (bStrEQ (S("TopMarginLandscape"), cp))
- X param0.TMargL = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("TopMarginPortrait"), cp))
- X param0.TMargP = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (bStrEQ (S("TopSkip"), cp))
- X param0.TSkip = mra2bp (ap, cp, 0.0, MM(100.0));
- Xelse if (NULBSTR != (p = prefix (S("Undefine"), cp)))
- X undef (p, ap);
- Xelse if (bStrEQ (S("VariableWidthBodyFont"), cp))
- X param0.VWFont = mcpstr (ap);
- Xelse if (bStrEQ (S("XAdjust"), cp))
- X param0.XAdjust = mra2bp (ap, cp, MM(-50.0), MM(50.0));
- Xelse if (bStrEQ (S("YAdjust"), cp))
- X param0.YAdjust = mra2bp (ap, cp, MM(-50.0), MM(50.0));
- Xelse malf1 (eCmd, fn, ln, cp, ap);
- X}
- X
- X/* cpStdin - copy standard input to temporary file */
- X
- XPRIVATE void cpStdin (fp)
- XR1 filT *fp; /* Points to data for file.*/
- X
- X/* Function:
- X * This is the result of a "File -" command. The standard input
- X * must be copied to a temporary file because cz needs to read it
- X * twice. If there was no Header command, make the header
- X * "Standard Input."
- X * Algorithm:
- X * Make temporary file. Open it for append. Call mfcopy().
- X * Close files.
- X * Returns:
- X *
- X * Notes:
- X * 1) Don't exit on a read error, just write a warning.
- X */
- X{
- XR2 streamT tos; /* Temporary file output stream.*/
- Xstatic char tfnb2[] = "/tmp/czsXXXXXX"; /* Temporary file name buffer.*/
- X
- Xif (NULBSTR == fp->filHdr) fp->filHdr = sStdin;
- Xfp->filName = (bStrT) mktemp (tfnb2);
- Xtos = mfopen (fp->filName, "w+");
- Xfp->filTmp = TRUE;
- Xmfcopy (stdin, 0, sStdin, tos, 1, fp->filName);
- Xif (fclose (stdin)) malf0 (eClose, sStdin);
- Xmfclose (tos, fp->filName);
- Xif (DB(D_FILE)) FPRINTF (stderr, "stdin -> %s\n", fp->filName);
- X}
- X
- X/* cvcol - try to output one page column */
- X
- XPRIVATE int cvcol (fp, pc, clm, moc)
- XR6 filT *fp; /* Points to data for file to convert.*/
- XR7 unsigned pc; /* Page column number.*/
- XR9 unsigned clm; /* Max number of output lines in column.*/
- X unsigned moc; /* Max output column.*/
- X
- X/* Function:
- X * Attempt to emit one output column. The output goes to a temporary
- X * file, so if it fails, because of line overflow, the caller can
- X * fseek back to the beginning of the failed attempt.
- X * Algorithm:
- X * Loop until failure or until a complete column is output.
- X * Call cvline() to attempt to convert each line, and switch
- X * on the return code. On success, end of column, end of page,
- X * end of file in middle of line, or success (folded line),
- X * print the line, using the appropriate PostScript functions
- X * at the beginning and end of the line. One end of file at the
- X * beginning of a line or line overflow, don't print anything, just
- X * return the appropriate code.
- X * Returns:
- X * SUCCESS or R_* code.
- X * Notes:
- X * 1) Variable s is used for for loop control (when negative) and
- X * as return code (when non-negative). This is a common trick.
- X * 2) linNum is incremented at the *end* of an input line, so eln
- X * is 1 + linNum for folded lines.
- X */
- X{
- XR8 unsigned cl = 1; /* Output line number within column.*/
- XR5 unsigned eln; /* Effective line number.*/
- XR4 boolT p; /* Print this output line.*/
- XR2 bStrT pnb; /* PostScript procedure for beginning of line.*/
- XR3 bStrT pne; /* PostScript procedure for end of line.*/
- XR1 int s = -1; /* Return code.*/
- X char lns[20]; /* Line number string.*/
- X
- XFPRINTF (psts, "(%u)%u %s\n", pc, pc, PCOLB);
- Xfor (; s < 0; ++cl)
- X {
- X outBufP = outBuf;
- X p = FALSE;
- X psLinL = 0;
- X switch (s = cvline (fp, moc))
- X {
- X case SUCCESS:
- X case R_COLE:
- X case R_PAGEE:
- X case R_EOFM:
- X if (linCont)
- X {
- X pnb = PLLB;
- X pne = PLLE;
- X linCont = FALSE;
- X }
- X else
- X {
- X pnb = PSLB;
- X pne = PSLE;
- X }
- X if ((SUCCESS == s) && (cl != clm)) s = -1;
- X p = TRUE;
- X break;
- X case R_CONT:
- X if (linCont)
- X {
- X pnb = PMLB;
- X pne = PMLE;
- X }
- X else
- X {
- X pnb = PFLB;
- X pne = PFLE;
- X linCont = TRUE;
- X }
- X s = ((cl == clm) ? SUCCESS : -1);
- X p = TRUE;
- X break;
- X case R_EOFB:
- X if (1 != cl) s = R_EOFM;
- X break;
- X case R_OVFL:
- X break;
- X default:
- X malf1 (eIntern, "cvcol", __LINE__);
- X break;
- X }
- X if (p)
- X {
- X eln = linNum;
- X if (linCont) ++eln;
- X PSPUTC (EOS);
- X if ((0 != fp->filPara.LNMult) &&
- X ((0 == (eln % fp->filPara.LNMult)) || (eln==lines)))
- X SPRINTF (lns, "(%u)", eln);
- X else
- X STRCPY (lns, "()");
- X FPRINTF (psts, "%s%u %s\n%s%s%u %s\n", lns, eln, pnb,
- X outBuf, lns, eln, pne);
- X }
- X }
- XFPRINTF (psts, "(%u)%u %s\n", pc, pc, PCOLE);
- Xif (DB(D_COL)) FPRINTF (stderr, "cvcol (%u, %u, %u) = %d\n", pc, clm, moc, s);
- Xreturn (s);
- X}
- X
- X/* cvfile - convert one file into PostScript */
- X
- XPRIVATE void cvfile (fp)
- XR2 filT *fp; /* Points to data for file to convert.*/
- X
- X/* Function:
- X * Convert the file to PostScript.
- X * Algorithm:
- X * If the file is standard input, copy it to a temporary file.
- X * Call doTop() to generate the output that is the same for every page.
- X * Open the file and call preScan() to compute the starting number
- X * of page columns for each page (pc0), and starting orientation (por0).
- X * preScan also counts input lines. Open a temporary output file.
- X * The outer (mf) loop is executed once for each page.
- X * The inner (mp) loop is executed once for each page attempt.
- X * Start with pc0 and por0. Compute the maximum allowed output
- X * columns for this page attempt (moc) from pc, por, and the
- X * AutoFile, AutoLandscape, and AutoColumn data. Call cvpage()
- X * to make the try. On overflow, first try decreasing pc. If pc
- X * is 1, try going to landscape. Seek back to the beginning of the
- X * page and try again. At the end of the outer loop, step through
- X * each page and call putPage() to write it for real.
- X * Notes:
- X *
- X */
- X{
- XR9 streamT f; /* Input stream.*/
- XR10 long isp; /* Offset in input stream.*/
- XR8 boolT mf; /* More of file to read.*/
- XR3 unsigned moc; /* Max number of output columns to try.*/
- XR1 boolT mp; /* More of page to convert.*/
- X ncStatT ncs; /* Save nc state at beginning of page.*/
- XR11 long osp; /* Offset in output stream.*/
- XR14 unsigned pages; /* Pages of output for this file.*/
- XR5 unsigned pc; /* Current number of page columns.*/
- X unsigned pc0; /* Initial number of page columns.*/
- XR4 boolT por; /* Current page in portrait mode.*/
- X boolT por0; /* Initially portrait mode.*/
- XR7 unsigned pn; /* Page number.*/
- XR6 int s; /* Return code.*/
- XR12 unsigned sln; /* Save line number.*/
- X pageT pageBy[MPAGES + 2]; /* Offset in psts of each page.*/
- XR13 pageT *pp; /* Steps through pageBy[].*/
- Xstatic char tfnb1[] = "/tmp/czpXXXXXX"; /* Temporary file name buffer.*/
- X
- Xif (DB(D_FILE)) FPRINTF (stderr, "cvfile %s\n", fp->filName);
- Xif (bStrEQ (S("-"), fp->filName)) cpStdin (fp);
- Xif (!doTop (fp)) return;
- Xf = fopen (fp->filName, "r");
- Xif (NULSTRM == f)
- X {
- X malf0 (eOpen, fp->filName);
- X return;
- X }
- XpreScan (fp, f, &pc0, &por0);
- Xif (0 == pc0)
- X {
- X malf0 (eEmpty, fp->filName);
- X if (fclose (f)) malf0 (eClose, fp->filName);
- X if (fp->filTmp)
- X {
- X if (unlink (fp->filName)) malf0 (eUnlink, fp->filName);
- X }
- X return;
- X }
- Xif (NULCSTR == pstfn) pstfn = mktemp (tfnb1);
- Xpsts = mfopen (pstfn, "w+");
- Xnc = nc0;
- Xnc.ncIStrm = f;
- XlinNum = 0;
- Xpn = 0;
- Xpp = &pageBy[1];
- Xfor (mf = TRUE; mf;)
- X {
- X ++pn;
- X pc = pc0;
- X por = por0;
- X isp = ftell (f);
- X ncs = nc;
- X osp = ftell (psts);
- X sln = linNum;
- X for (mp = TRUE; mp;)
- X {
- X if (fp->filPara.AutoFil)
- X moc = MOCOL;
- X else if (por && (1 == pc))
- X moc = fp->filPara.AutoLnd;
- X else if (1 != pc)
- X moc = fp->filPara.AutoCol[pc];
- X else
- X moc = MOCOL;
- X s = cvpage (fp, pc, por, moc);
- X switch (s)
- X {
- X case R_EOFB:
- X --pn;
- X /* Falls through.*/
- X case R_EOFM:
- X mf = FALSE;
- X /* Falls through.*/
- X case SUCCESS:
- X case R_PAGEE:
- X mp = FALSE;
- X break;
- X case R_OVFL:
- X if (por && (1 == pc))
- X por = FALSE;
- X else if (1 != pc)
- X --pc;
- X else
- X malf1 (eIntern, "cvfile", __LINE__);
- X mfseek (f, isp, 0, fp->filName);
- X mfflush (psts, pstfn);
- X mfseek (psts, osp, 0, pstfn);
- X linNum = sln;
- X nc = ncs;
- X break;
- X default:
- X malf1 (eIntern, "cvfile", __LINE__);
- X break;
- X }
- X }
- X if (pn > MPAGES) malf1 (eMPages, fp->filName, MPAGES);
- X if (R_EOFB != s)
- X {
- X mfflush (psts, pstfn);
- X pp->pgPos = osp;
- X pp->pgCols = pc;
- X pp->pgPor = por;
- X ++pp;
- X if (DB(D_PAGE))
- X FPRINTF (stderr, "page %u: %u cols %s\n", pn,
- X pc, por ? "portrait" : "landscape");
- X }
- X }
- Xif (ferror (f)) malf0 (eReadL, fp->filName, linNum);
- Xif (fclose (f)) malf0 (eClose, fp->filName);
- Xif (fp->filTmp)
- X {
- X if (unlink (fp->filName)) malf0 (eUnlink, fp->filName);
- X }
- Xpages = pn;
- Xif (Reverse)
- X {
- X pp->pgPos = ftell (psts);
- X for (--pp; pp != pageBy; --pp)
- X putPage (fp, pp, pn--, pages, pp[1].pgPos - pp->pgPos);
- X }
- Xelse
- X {
- X pn = 1;
- X pp->pgPos = ftell (psts);
- X for (pp = &pageBy[1]; pn <= pages; ++pp)
- X putPage (fp, pp, pn++, pages, pp[1].pgPos - pp->pgPos);
- X }
- Xif (fclose (psts)) malf0 (eClose, pstfn);
- XtotPag += pages;
- X}
- X
- X/* cvline - Try to convert one output line to PostScript */
- X
- XPRIVATE int cvline (fp, moc)
- XR9 filT *fp; /* Points to data for file to convert.*/
- XR8 unsigned moc; /* Max output column.*/
- X
- X/* Function:
- X * Attempt to convert one output line. The output goes into a buffer;
- X * it is not written onto the temporary file here. This is because
- X * the output must be preceded by a call to the appropriate PostScript
- X * procedure, but which one is appropriate depends on whether the line
- X * is folded.
- X * Algorithm:
- X * Loop. Call nextc() to get next input character and convert it
- X * to nextc() output form, which is an array of unsigned shorts.
- X * Elements less than 256 are literal bytes to be output; other
- X * elements are from the T_* codes, with a bias of 256.
- X * (T_END + 256) marks the end of the array.
- X *
- X * Set endF if this character ends the line in some way.
- X * Set tabF is this character is a tab. Compute the number of
- X * spaces. (The -1 is because nextc() has already incremented
- X * nc.ncICol and oCol.) Check for output column overflow and folding.
- X * Step through each element in the array. Put literal bytes into
- X * the buffer and switch on the T_* codes. If a PostScript line
- X * could become longer than MPSLINE characters, force the end of a
- X * string.
- X * Returns:
- X * Return code.
- X * Notes:
- X * 1) The ENDSTR macro assumes that PSPUTC is one character.
- X * 2) Warning messages for undefined characters have already
- X * been printed in the preScan() pass.
- X */
- X{
- X/* If outputting a PostScript string, end it:*/
- X#define ENDSTR {if(ins){PSPUTC(')');PSPUTC(*PSHOW);PSPUTC('\n');ins=FALSE;}}
- XR2 ushrtT *pp; /* Returned by nextc().*/
- XR1 ushrtT *pp2; /* Steps through pp[].*/
- XR3 boolT endF; /* T_{LINE,COLE,PAGEE,EOF} in pp[].*/
- XR4 boolT tabF; /* T_TAB in pp[].*/
- XR5 boolT ins = FALSE; /* Flag set when PS string being output.*/
- XR6 int s = -1; /* Loop control and return code.*/
- XR7 unsigned spcs; /* Tab expands into this many spaces.*/
- XR10 int i; /* Count octets.*/
- X
- XoCol = 0;
- Xwhile (s < 0)
- X {
- X pp = nextc();
- X endF = FALSE;
- X tabF = FALSE;
- X for (pp2 = pp; (T_END + 256) != *pp2; ++pp2)
- X {
- X if (((T_LINEE + 256) == *pp2) || ((T_COLE + 256) == *pp2) ||
- X ((T_PAGEE + 256) == *pp2) || ((T_EOF + 256) == *pp2))
- X endF = TRUE;
- X else if ((T_TAB + 256) == *pp2)
- X tabF = TRUE;
- X }
- X if (!tabF)
- X spcs = 1;
- X else
- X {
- X spcs = fp->filPara.TabWid - ((nc.ncICol - 1) % fp->filPara.TabWid);
- X nc.ncICol += spcs - 1;
- X oCol += spcs - 1;
- X }
- X if (!endF)
- X {
- X if (oCol >= moc)
- X s = R_OVFL;
- X else if (oCol >= (linCont ? fp->filPara.FoldRst : fp->filPara.FoldFst))
- X {
- X if (nc.ncUn) malf1 (eIntern, "cvline", __LINE__);
- X nc.ncUn = TRUE;
- X nc.ncICol -= spcs;
- X s = R_CONT;
- X }
- X }
- X if (s < 0)
- X {
- X do
- X {
- X if (*pp <= 256)
- X PSPUTC (*pp);
- X else
- X {
- X switch (*pp - 256)
- X {
- X case T_UNDEF:
- X ENDSTR;
- X PSPUTC ('(');
- X if (fp->filPara.FixWid)
- X SPRINTF (outBufP, "%02X", nc.ncOb[nc.ncN - 1]);
- X else
- X {
- X SPRINTF (outBufP, "%o", nc.ncOb[0]);
- X for (i = 1; i != nc.ncN; ++i)
- X {
- X outBufP = strend (outBufP);
- X SPRINTF (outBufP, " %o", nc.ncOb[i]);
- X }
- X }
- X outBufP = strend (outBufP);
- X SPRINTF (outBufP, ")%s", PUNDEF);
- X outBufP = strend (outBufP);
- X PSPUTC ('\n');
- X break;
- X case T_TAB:
- X if (!ins)
- X {
- X PSPUTC ('(');
- X ins = TRUE;
- X }
- X while (spcs--)
- X PSPUTC (' ');
- X break;
- X case T_STRB:
- X if (!ins)
- X {
- X PSPUTC ('(');
- X ins = TRUE;
- X }
- X break;
- X case T_STRE:
- X ENDSTR;
- X break;
- X case T_LINEE:
- X ++linNum;
- X nc.ncICol = 0;
- X s = SUCCESS;
- X break;
- X case T_COLE:
- X s = R_COLE;
- X break;
- X case T_PAGEE:
- X s = R_PAGEE;
- X break;
- X case T_EOF:
- X s = ((0 == oCol) ? R_EOFB : R_EOFM);
- X break;
- X }
- X }
- X }
- X while ((T_END + 256) != *++pp);
- X }
- X if (!ins)
- X PSPUTC ('\n');
- X else if (psLinL > (MPSLINE - MMULOCT * MPSSTR - 1))
- X ENDSTR;
- X }
- XENDSTR;
- Xif (DB(D_LINE)) FPRINTF (stderr, "cvline %u = %d\n", linNum, s);
- Xreturn (s);
- X}
- X
- X/* cvpage - try to convert one page to PostScript */
- X
- XPRIVATE int cvpage (fp, pc, por, moc)
- XR4 filT *fp; /* Points to data for file to convert.*/
- XR3 unsigned pc; /* Page columns to try.*/
- X boolT por; /* Portrait mode.*/
- XR6 unsigned moc; /* Max input column.*/
- X
- X/* Function:
- X * Try to convert one page.
- X * Algorithm:
- X * Compute clm, the maximum number of output lines that will fit
- X * in one output column. This has to be recomputed for each page
- X * attempt because pc and por can be different. Loop over the
- X * page columns. Call cvcol() to try to convert one column, and
- X * switch on the return code.
- X * Returns:
- X * Return code.
- X * Notes:
- X *
- X */
- X{
- X double bodHt; /* Body height.*/
- XR2 unsigned c = 1; /* Current page column.*/
- XR5 unsigned clm; /* Max number of output lines in a page column.*/
- XR7 paramT *p = &fp->filPara;
- X double leading = p->BodySiz * p->Spacing; /* Space between lines.*/
- XR1 int s; /* Return code.*/
- X double yHead; /* Y coordinate of header baseline.*/
- X
- Xif (por)
- X {
- X yHead = p->PageHt - p->TMargP - p->HeadHt;
- X if (yHead <= 0.0) malf1 (eBigHd, p->TMargP + p->HeadHt, p->PageHt);
- X bodHt = yHead - p->TSkip - p->BSkip - p->FootHt - p->BMargL;
- X }
- Xelse
- X {
- X yHead = p->PageWid - p->TMargL - p->HeadHt;
- X if (yHead <= 0.0) malf1 (eBigHd, p->TMargL + p->HeadHt, p->PageWid);
- X bodHt = yHead - p->TSkip - p->BSkip - p->FootHt - p->BMargP;
- X }
- Xif (bodHt < leading) malf1 (eNoBod, bodHt, leading);
- Xclm = (unsigned)(bodHt / leading);
- Xfor (s = -1; s < 0; ++c)
- X {
- X switch (s = cvcol (fp, c, clm, moc))
- X {
- X case SUCCESS:
- X case R_COLE:
- X s = ((c == pc) ? SUCCESS : -1);
- X break;
- X case R_EOFM:
- X case R_PAGEE:
- X case R_OVFL:
- X break;
- X case R_EOFB:
- X if (1 != c) s = R_EOFM;
- X break;
- X default:
- X malf1 (eIntern, "cvpage", __LINE__);
- X break;
- X }
- X }
- Xif (DB(D_PAGEA))
- X FPRINTF (stderr, "cvpage (%u, %s, %u) = %d\n", pc,
- X por ? "portrait" : "landscape", moc, s);
- Xreturn (s);
- X}
- X
- X/* docFnts - output %%DocumentFonts: comment */
- X
- XPRIVATE void docFnts()
- X
- X/* Function:
- X * Write the DocumentFonts structure comment that lists all fonts
- X * used. Get as many font names on a line as possible, without
- X * exceeding MPSLINE. Use the %%+ line continuation convention
- X * if necessary.
- X * Algorithm:
- X * Step through fonts[], write each font name, and keep track of
- X * the output column.
- X * Returns:
- X *
- X * Notes:
- X *
- X */
- X{
- XR2 unsigned c; /* Output column.*/
- XR1 fontT *fp; /* Steps through fonts[].*/
- XR3 unsigned l; /* Length of font name and leading space.*/
- Xstatic char df[] = "%%DocumentFonts:";
- X
- Xc = strlen (df);
- XFPUTS (df, psos);
- Xfor (fp = fonts; fp != fontP; ++fp)
- X {
- X l = 1 + strlen (fp->fntName);
- X if ((c + l) >= MPSLINE)
- X {
- X FPUTS ("\n%%+", psos);
- X c = 0;
- X }
- X PUTC (' ', psos);
- X FPUTS (fp->fntName, psos);
- X c += l;
- X }
- XPUTC ('\n', psos);
- X}
- X
- X/* doTop - set up topBuf[] for a new file */
- X
- XPRIVATE boolT doTop (fp)
- XR3 filT *fp; /* Points to data for file to convert.*/
- X
- X/* Function:
- X * There is some repetitive stuff at the beginning of every page
- X * that is the same for every file. It's repeated so that every
- X * PostScript page is independent of every other page. This
- X * allows page reversal, page selection, and parallel page interpretation.
- X * This function generates the constant top-of-page stuff, and
- X * places it in the topBuf[] buffer.
- X * Algorithm:
- X * Store the constant defs. Call cvline() to store the header.
- X * Returns:
- X * TRUE of success; FALSE on error.
- X * Notes:
- X *
- X */
- X{
- XR2 paramT *p = &fp->filPara;
- XR1 bStrT tp; /* Steps through topBuf[].*/
- X
- Xtp = topBuf;
- XSPRINTF (tp, "%s\n", PSAVE);
- Xtp = strend (tp);
- XSPRINTF (tp, "/%s /%sE %s\n", PFONT, p->FixWid ? p->FWFont : p->VWFont,
- X PDEF);
- Xtp = strend (tp);
- XSPRINTF (tp, "/%s /%sE %s\n", FOOTFNT, p->FootFnt, PDEF);
- Xtp = strend (tp);
- XSPRINTF (tp, "/%s /%sE %s\n", HEADFNT, p->HeadFnt, PDEF);
- Xtp = strend (tp);
- XSPRINTF (tp, "/%s /%sE %s\n", PLNFNT, p->LNFnt, PDEF);
- Xtp = strend (tp);
- XSPRINTF (tp, "/%s /%s %s\n", SYMBFNT, p->SymbFnt, PDEF);
- Xtp = strend (tp);
- XSPRINTF (tp, "/%s %s %s\n", PFIXWID, p->FixWid ? "true" : "false", PDEF);
- XoutBufP = strend (tp);
- XoutBufE = &topBuf[MTOPBUF];
- XputDimO (BODYSIZ, p->BodySiz);
- XputDimO (PFOOTHT, p->FootHt);
- XputDimO (PHEADHT, p->HeadHt);
- XputDimO (LEADING, p->BodySiz * p->Spacing);
- XputDimO (PLNHT, p->LNHt);
- XputDimO (PLNWID, p->LNWid);
- XputDimO (XADJUST, p->XAdjust);
- XputDimO (YADJUST, p->YAdjust);
- XSPRINTF (outBufP, "/%s", PHEADER);
- XoutBufP = strend (outBufP);
- XPSPUTC ('\n');
- XPSPUTC ('{');
- XPSPUTC ('\n');
- Xnc = nc0;
- Xnc.ncFP = fp;
- Xif (NULBSTR == fp->filHdr) fp->filHdr = fp->filName;
- Xnc.ncStr = fp->filHdr;
- Xswitch (cvline (fp, MOCOL))
- X {
- X case R_EOFB:
- X case R_EOFM:
- X break;
- X case SUCCESS:
- X malf0 (eHdrEnd, "line", fp->filName, fp->filHdr);
- X return (FALSE);
- X case R_COLE:
- X malf0 (eHdrEnd, "column", fp->filName, fp->filHdr);
- X return (FALSE);
- X case R_PAGEE:
- X malf0 (eHdrEnd, "page", fp->filName, fp->filHdr);
- X return (FALSE);
- X default:
- X malf1 (eIntern, "cvfile", __LINE__);
- X break;
- X }
- XPSPUTC ('}');
- XSTRCPY (outBufP, PDEF);
- XoutBufP = strend (outBufP);
- XPSPUTC ('\n');
- XPSPUTC (EOS);
- Xnc = nc0;
- Xreturn (TRUE);
- X}
- X
- X/* headCom - output PostScript structure header comments */
- X
- XPRIVATE void headCom()
- X
- X/* Function:
- X * Output the structure comments at the beginning of the PostScript
- X * output.
- X * Algorithm:
- X *
- X * Returns:
- X *
- X * Notes:
- X * 1) The %%For: line is entirely optional. If your system
- X * has any trouble with the code to generate it, you can
- X * safely comment it out.
- X */
- X{
- XR1 struct tm *tmp; /* Returned by localtime().*/
- X long ut; /* Current system time.*/
- X byteT fnb[1024]; /* Store user's full name here.*/
- Xextern long time(); /* (3C).*/
- X
- XFPUTS ("%!PS-Adobe-2.1\n", psos);
- XFPRINTF (psos, "%%%%Creator: cz%d.%d\n", FRZ_MAJ, FRZ_MIN);
- Xut = time ((long *) NULL);
- Xtmp = localtime (&ut);
- XFPRINTF (psos, "%%%%CreationDate: %d-%02d-%02d %02d:%02d:%02d\n",
- X 1900 + tmp->tm_year, 1 + tmp->tm_mon, tmp->tm_mday,
- X tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- Xif (NULBSTR != userfn (fnb)) FPRINTF (psos, "%%%%For: %s\n", fnb);
- XFPUTS ("%%Pages: (atend)\n", psos);
- XFPUTS ("%%DocumentFonts: (atend)\n", psos);
- X}
- X
- X/* init - initialize at start of execution */
- X
- XPRIVATE void init()
- X
- X/* Function:
- X * Initialize some things.
- X * Algorithm:
- X *
- X * Returns:
- X *
- X * Notes:
- X * 1) The umask setting will make the temporary files unreadable by
- X * others than the creator, for security.
- X */
- X{
- XR1 bStrT bp1; /* Steps through ncMap[].*/
- XR2 bStrT bp2; /* End of ncMap[].*/
- XR5 int i; /* Loop counter.*/
- XR3 ushrtT *up1; /* Steps through AutoCol[].*/
- XR4 ushrtT *up2; /* End of AutoCol[].*/
- Xextern int umask(); /* (2).*/
- X
- X(void) umask (0077);
- Xnc0.ncStr = NULBSTR;
- Xbp1 = ncMap;
- Xbp2 = &ncMap[256];
- Xwhile (bp1 != bp2)
- X *bp1++ = T_RES;
- XncMap[E_STRB] = T_STRB;
- XncMap[E_STRE] = T_STRE;
- XncMap[E_COM] = T_COM;
- XncMap[E_EESC] = T_EESC;
- XncMap[E_COLE] = T_COLE;
- XncMap[E_LINEE] = T_LINEE;
- XncMap[E_PAGEE] = T_PAGEE;
- XncMap[E_TAB] = T_TAB;
- Xup1 = param0.AutoCol;
- Xup2 = up1 + MPAGCOL + 1;
- Xwhile (up1 != up2)
- X *up1++ = MOCOL;
- Xparam0.AutoLnd = MOCOL;
- Xfor (i = 1; MSTATE != i; ++i)
- X states[i] = (stateT *) NULL;
- X#include "cz0-init.h"
- X}
- X
- X/* mpsputc - handle output buffer overflow */
- X
- XPRIVATE void mpsputc ()
- X
- X/* Function:
- X * The buffer in which PSPUTC stores bytes has overflowed.
- X Write an error message.
- X * Algorithm:
- X * Figure out which buffer and call malf1().
- X * Returns:
- X * No return.
- X * Notes:
- X *
- X */
- X{
- Xif (&outBuf[MOUTBUF] == outBufE)
- X malf1 (ePSPutC, "outBuf", MOUTBUF);
- Xelse if (&topBuf[MTOPBUF] == outBufE)
- X malf1 (ePSPutC, "topBuf", MTOPBUF);
- Xelse
- X malf1 (eIntern, "mpsputc", __LINE__);
- X}
- X
- X/* mra2bp - convert string to typographical units and check for errors */
- X
- XPRIVATE double mra2bp (s, n, l, h)
- XR3 bStrT s; /* Input string.*/
- X bStrT n; /* Name of field, for error messages.*/
- X double l; /* Lower bound.*/
- X double h; /* Upper bound.*/
- X
- X/* Function:
- X * String s is supposed to be a real numeric literal followed by a
- X * two-letter units abbreviation. Convert it to big points.
- X * Algorithm:
- X * Linear search on units, then call mra2d().
- X * Returns:
- X * PostScript internal units.
- X * Notes:
- X * 1) Maybe I should use perfect hashing on the units?
- X * 2) For now, loose syntax is allowed, e.g. 0bp. But this is not
- X * documented, so I can tighten up whenever I want.
- X */
- X{
- X double sf; /* Scaling factor.*/
- XR2 int ls; /* Length of input string.*/
- XR1 bStrT p; /* Should point to units.*/
- X
- Xif (DB(D_PSC)) FPRINTF (stderr, "mra2bp (%s, %s, %G, %G)\n", s, n, l, h);
- Xls = strlen (s);
- Xif (ls < 3) malf1 ("%s [%s]: Bad format", n, s);
- Xp = &s[ls - 2];
- Xif (bStrEQ (S("bp"), p)) sf = 1.0;
- Xelse if (bStrEQ (S("cc"), p)) sf = CF_CC;
- Xelse if (bStrEQ (S("cm"), p)) sf = CF_CM;
- Xelse if (bStrEQ (S("dd"), p)) sf = CF_DD;
- Xelse if (bStrEQ (S("in"), p)) sf = CF_IN;
- Xelse if (bStrEQ (S("mm"), p)) sf = CF_MM;
- Xelse if (bStrEQ (S("pc"), p)) sf = CF_PC;
- Xelse if (bStrEQ (S("pt"), p)) sf = CF_PT;
- Xelse malf1 (eUnits, n, s, p);
- Xreturn (sf * mra2d (s, p, TRUE, n, l, h, (bStrT *) NULL));
- X}
- X
- X/* ms2bool - convert string to Boolean and handle errors */
- X
- XPRIVATE boolT ms2bool (s, fn)
- XR1 bStrT s; /* Input string.*/
- X bStrT fn; /* Field name.*/
- X
- X/* Function:
- X * Convert string representations of Booleans to internal representation.
- X * Algorithm:
- X * Linear search.
- X * Returns:
- X * TRUE or FALSE. No return on error.
- X * Notes:
- X * 1) Case is significant.
- X */
- X{
- Xif (bStrEQ (S("false"), s)) return (FALSE);
- Xelse if (bStrEQ (S("true"), s)) return (TRUE);
- Xelse malf1 ("%s [%s] neither false nor true", s, fn);
- X/*NOTREACHED*/
- X}
- X
- X/* nextc - get next input character */
- X
- XPRIVATE ushrtT *nextc()
- X
- X/* Function:
- X * Convert one input character to output format. The input character
- X * can come from a stream or a string (for headers). A character
- X * can be up to MMULOCT bytes. Output format is an array of unsigned
- X * shorts. Elements in the range [0, 255] are bytes to be output literally.
- X * Higher elements are one of the T_* codes biased by 256.
- X * (T_END + 256) marks the end of the array.
- X * Algorithm:
- X * If previous result was pushed back by line folding, unpush it and return.
- X * Otherwise, start in state 0 and loop. Get one byte from the string
- X * or stream. Handle end of string/file. Get the state-octet entry.
- X * Step through the PostScript. Copy ordinary characters to the return
- X * buffer, but switch on escapes.
- X * Returns:
- X * A pointer to the array.
- X * Notes:
- X *
- X */
- X{
- XR7 stateT *sp; /* Points to current stateT.*/
- XR4 soT *sop; /* Points to current state-octet pair.*/
- XR6 boolT m; /* More to do.*/
- XR5 unsigned st; /* State.*/
- XR3 ushrtT *rbp; /* Steps through return buffer.*/
- XR9 bStrT obp; /* Steps through octet buffer.*/
- XR8 rcharT o; /* Current input octet.*/
- XR1 unsigned p; /* Current result byte.*/
- XR2 bStrT psp; /* Steps through PostScript for each state-octet pair.*/
- X
- Xif (nc.ncUn)
- X {
- X nc.ncUn = FALSE;
- X return (nc.ncRb);
- X }
- Xst = 0;
- Xobp = nc.ncOb;
- Xrbp = nc.ncRb;
- Xfor (m = TRUE; m;)
- X {
- X if (NULBSTR != nc.ncStr)
- X {
- X o = B(*nc.ncStr);
- X ++nc.ncStr;
- X if (EOS == o)
- X {
- X if (0 != st)
- X {
- X malf0 (eEOSSt, st, nc.ncFP->filHdr);
- X st = 0;
- X }
- X o = EOF;
- X }
- X }
- X else
- X {
- X o = getc (nc.ncIStrm);
- X if (EOF == o)
- X {
- X if (ferror (nc.ncIStrm)) malf0 (eRead, nc.ncFP->filName);
- X if (0 != st)
- X {
- X malf0 (eEOFSt, nc.ncFP->filName, st);
- X st = 0;
- X }
- X }
- X }
- X if (EOF == o)
- X {
- X *rbp++ = T_EOF + 256;
- X m = FALSE;
- X }
- X else
- X {
- X if ((o < 0) || (o > 255)) malf1 (eIntern, "nextc", __LINE__);
- X *obp++ = o;
- X if (0 == st)
- X {
- X ++nc.ncICol;
- X ++oCol;
- X }
- X p = 0;
- X sp = states[st];
- X if (((stateT *) NULL) == sp)
- X {
- X if (DB(D_OCT)) FPRINTF (stderr, "State %u undefined\n", st);
- X p = T_UNDEF + 256;
- X }
- X else
- X {
- X sop = ((soT *) sp) + o;
- X psp = sop->so_ps;
- X if (DB(D_OCT))
- X FPRINTF (stderr, "State %u Octet %c 8#%o# (%s%c%c%u)\n",
- X st, o, o, psp, E_ESC, E_NEXTS, sop->so_nxt);
- X if (NULBSTR == psp) p = T_UNDEF + 256;
- X }
- X if ((T_UNDEF + 256) == p)
- X {
- X rbp = nc.ncRb;
- X *rbp++ = p;
- X st = 0;
- X }
- X else
- X {
- X for (; EOS != (p = B(*psp)); ++psp)
- X {
- X if (E_ESC != p)
- X *rbp++ = p;
- X else
- X {
- X ++psp;
- X p = ncMap[B(*psp)];
- X switch (p)
- X {
- X case T_RES: /* Can't happen.*/
- X malf1 (eMap, E_ESC, *psp, *psp, st, o, o);
- X break;
- X case T_COM:
- X *rbp++ = COMMENT;
- X break;
- X case T_EESC:
- X *rbp++ = E_ESC;
- X break;
- X default:
- X *rbp++ = p + 256;
- X break;
- X }
- X }
- X }
- X st = sop -> so_nxt;
- X }
- X }
- X if (0 == st) m = FALSE;
- X }
- X*rbp = T_END + 256;
- Xnc.ncN = obp - nc.ncOb;
- Xif (DB(D_PSC))
- X {
- X for (rbp = nc.ncRb; (T_END + 256) != *rbp; ++rbp)
- X {
- X if (*rbp < 256)
- X PUTC (*rbp, stderr);
- X else
- X {
- X switch (*rbp - 256)
- X {
- X case T_UNDEF:
- X FPRINTF (stderr, "%cU", E_ESC);
- X break;
- X case T_STRB:
- X FPRINTF (stderr, "%c%c", E_ESC, E_STRB);
- X break;
- X case T_STRE:
- X FPRINTF (stderr, "%c%c", E_ESC, E_STRE);
- X break;
- X case T_TAB:
- X FPRINTF (stderr, "%c%c(%u)", E_ESC, E_TAB, nc.ncICol);
- X break;
- X case T_COLE:
- X FPRINTF (stderr, "%c%c", E_ESC, E_COLE);
- X break;
- X case T_LINEE:
- X FPRINTF (stderr, "%c%c", E_ESC, E_LINEE);
- X break;
- X case T_PAGEE:
- X FPRINTF (stderr, "%c%c", E_ESC, E_PAGEE);
- X break;
- X case T_EOF:
- X FPRINTF (stderr, "%cE", E_ESC);
- X break;
- X default:
- X malf1 (eIntern, "nextc", __LINE__);
- X break;
- X }
- X }
- X }
- X PUTC ('\n', stderr);
- X }
- Xreturn (nc.ncRb);
- X}
- X
- X/* preScan - find widest line in input file, and count lines */
- X
- XPRIVATE void preScan (fp, f, pcp, porp)
- X filT *fp; /* Points to data for file to convert.*/
- XR8 streamT f; /* Input stream.*/
- X unsigned *pcp; /* Store initial number of page columns here.*/
- X boolT *porp; /* Store initial orientation here.*/
- X
- X/* Function:
- X * If AutoColumn or AutoLandscape are being done on a whole-file
- X * basis (AutoFile true), then we need to know the widest line in
- X * the file. Also, we need to know the number of lines in the file
- X * so we can always output the line number of the last one.
- X * This function reads through the entire file and then rewinds it
- X * for the conversion pass.
- X * Algorithm:
- X * Loop through each input character. Switch on T_* codes.
- X * Expand tabs. On end of line set mc = max (mc, oCol).
- X * At the end of the loop, compute pc0 and por0.
- X * Returns:
- X * Stores pc0 in *pcp and por0 in *porp. pc0 is 0 for an empty file.
- X * Notes:
- X * 1) This pass could be avoided if AutoFile is false and line numbers
- X * are not being printed.
- X */
- X{
- XR4 boolT nl = TRUE; /* Start of new line.*/
- XR5 unsigned mc = 0; /* Max input columns in file.*/
- XR6 unsigned mcl = 0; /* Line number of (first) widest line in file.*/
- XR2 paramT *p = &fp->filPara;
- XR7 unsigned pc; /* Initial page columns.*/
- XR1 ushrtT *pp; /* Returned by nextc().*/
- XR3 unsigned spcs; /* Tab expands into this many spaces.*/
- X
- XlinNum = 0;
- XoCol = 0;
- Xnc.ncIStrm = f;
- Xpp = nextc();
- Xdo
- X {
- X if ((T_END + 256) == *pp) pp = nextc();
- X if (*pp <= 256)
- X nl = FALSE;
- X else
- X {
- X switch (*pp - 256)
- X {
- X case T_TAB:
- X spcs = p->TabWid - ((nc.ncICol - 1) % p->TabWid) - 1;
- X nc.ncICol += spcs;
- X oCol += spcs;
- X nl = FALSE;
- X break;
- X case T_UNDEF:
- X malf0 (eUndef, fp->filName, linNum + 1);
- X /* Falls through.*/
- X case T_STRB:
- X case T_STRE:
- X nl = FALSE;
- X break;
- X case T_LINEE:
- X ++linNum;
- X nc.ncICol = 0;
- X if (oCol > mc)
- X {
- X mcl = linNum;
- X mc = oCol;
- X }
- X nl = TRUE;
- X oCol = 0;
- X break;
- X case T_COLE:
- X case T_PAGEE:
- X if (oCol > mc)
- X {
- X mcl = linNum + 1;
- X mc = oCol;
- X }
- X oCol = 0;
- X break;
- X case T_EOF:
- X if (!nl) malf0 (eEOF, fp->filName, linNum + 1);
- X if (oCol > mc)
- X {
- X mcl = linNum + 1;
- X mc = oCol;
- X }
- X break;
- X default:
- X malf1 (eIntern, "cvfile", __LINE__);
- X break;
- X }
- X }
- X }
- Xwhile ((T_EOF + 256) != *pp++);
- Xif (0 == mc)
- X { /* Empty file.*/
- X *pcp = 0;
- X return;
- X }
- Xlines = linNum;
- X--mc;
- Xif (p->AutoFil)
- X {
- X for (pc = p->Columns; (1 != pc) && (mc > p->AutoCol[pc]); --pc)
- X ;
- X *porp = (mc <= p->AutoLnd);
- X }
- Xelse
- X {
- X pc = p->Columns;
- X *porp = (0 != p->AutoLnd);
- X }
- X*pcp = pc;
- Xrewind (f);
- XlinCont = FALSE;
- XoutBufE = &outBuf[MOUTBUF];
- Xif (DB(D_FILE))
- X FPRINTF (stderr,
- X "preScan: widest line: %u (%u cols)\n\ttotal lines: %u\n\tinitial page columns: %u %s\n",
- X mcl, mc, linNum, pc, *porp ? "portrait" : "landscape");
- X}
- X
- X/* psputc - append one byte to output buffer */
- X
- XPRIVATE void psputc (c)
- XR1 rcharT c; /* Byte to append.*/
- X
- X/* Function:
- X * Store c in the output buffer. Handle long lines and buffer overflow.
- X * Algorithm:
- X * psLinL is the current number of bytes already output on the current
- X * output line. Just ignore a newline after another newline.
- X * Returns:
- X *
- X * Notes:
- X * 1) This is inefficient. We shouldn't be copying so many bytes around.
- X * We should use pointers instead.
- X */
- X{
- Xif ('\n' == c)
- X {
- X if (0 != psLinL)
- X {
- X *outBufP++ = c;
- X psLinL = 0;
- X }
- X }
- Xelse
- X {
- X *outBufP++ = c;
- X ++psLinL;
- X }
- Xif (outBufP >= outBufE) mpsputc();
- X}
- X
- X/* putDim - write a dimension to output buffer */
- X
- XPRIVATE void putDim (a, v)
- XcStrT a; /* Abbreviation string for dimension.*/
- Xdouble v; /* Value of dimension.*/
- X
- X/* Function:
- X * Write a def directly to the output stream.
- X * Algorithm:
- X *
- X * Returns:
- X *
- X * Notes:
- X * 1) Two decimal places are enough precision for printers with up
- X * to 7200 dots per inch resolution.
- X */
- X{
- XFPRINTF (psos, "/%s %.2f %s\n", a, v, PDEF);
- X}
- X
- X/* putDimO - write a dimension to output buffer */
- X
- XPRIVATE void putDimO (a, v)
- XcStrT a; /* Abbreviation string for dimension.*/
- Xdouble v; /* Value of dimension.*/
- X
- X/* Function:
- X * Store a def in the output buffer.
- X * Algorithm:
- X * The first call to PSPUTC makes psLinL nonzero for the second call.
- X * Otherwise the second call would be ignored. The second call
- X * checks for output buffer overflow.
- X * Returns:
- X *
- X * Notes:
- X *
- X */
- X{
- XPSPUTC ('/');
- XSPRINTF (outBufP, "%s %.2f %s", a, v, PDEF);
- XoutBufP = strend (outBufP);
- XPSPUTC ('\n');
- X}
- X
- X/* putFnts - write definition for each font used */
- X
- XPRIVATE void putFnts()
- X
- X/* Function:
- X * Create the list of all fonts used by all files in the job.
- X * Output reencode commands for all fonts used except symbol fonts.
- X * Algorithm:
- X * Loop through each file. Call addFnt() for each font.
- X * Then loop through each font.
- X * Returns:
- X *
- X * Notes:
- X *
- X */
- X{
- XR1 filT *fp; /* Steps through fil[].*/
- XR2 fontT *fnp; /* Steps through fonts[].*/
- XR3 paramT *p; /* &fp->filPara.*/
- X
- Xfor (fp = &fil[1]; fp != filp; ++fp)
- X {
- X p = &fp->filPara;
- X addFnt (p->FixWid ? p->FWFont : p->VWFont, FALSE);
- X addFnt (p->FootFnt, FALSE);
- X addFnt (p->HeadFnt, FALSE);
- X addFnt (p->LNFnt, FALSE);
- X addFnt (p->SymbFnt, TRUE);
- X }
- Xfor (fnp = fonts; fnp != fontP; ++fnp)
- X {
- X if (!fnp->fntSymb)
- X FPRINTF (psos, "/%sE /%s %s\n", fnp->fntName, fnp->fntName, REENCOD);
- X }
- X}
- X
- X/* putPage - Write one page to psos */
- XPRIVATE void putPage (fp, pp, pn, tp, nb)
- XR4 filT *fp; /* Points to file data.*/
- XR7 pageT *pp; /* Points to data for page.*/
- XR5 unsigned pn; /* Page number.*/
- XR6 unsigned tp; /* Total number of pages in file.*/
- XR2 long nb; /* Number of bytes to copy from temporary file.*/
- X
- X/* Function:
- X *
- X * Algorithm:
- X * The width available for one column is the (effective) page width
- X * less the left and right margins and column separation gutters,
- X * all divided by the number of columns.
- X * The maximum number of lines per column is the (effective) page
- X * height less the top and bottom margins and header and footer,
- X * divided by the distance between lines, then rounded down.
- X *
- X * Output all the dimensions, then copy bytes.
- X * Returns:
- X *
- X * Notes:
- X * 1) I have no idea if the TxtVert code is the right thing to do.
- X * The theory is that landscaped vertical text should be like
- X * portrait horizontal text, and vice versa.
- X * 2) It would be faster to copy the bytes in big chunks, not
- X * one at a time.
- X */
- X{
- XR1 rcharT c; /* Current byte from temp file.*/
- XR3 paramT *p = &fp->filPara;
- X double cw; /* Page column width.*/
- X double ePageHt; /* Effective page height.*/
- X double ePageWid; /* Effective page width.*/
- X double eLMarg; /* Effective left margin.*/
- X double eRMarg; /* Effective right margin.*/
- X double eTMarg; /* Effective top margin.*/
- X double eBMarg; /* Effective bottom margin.*/
- X
- Xmfseek (psts, pp->pgPos, 0, pstfn);
- XFPRINTF (psos, "%%%%Page: %s-%u %u\n", fp->filName, pn, pn + totPag);
- XFPUTS (topBuf, psos);
- Xif (pp->pgPor != p->TxtVert)
- X {
- X ePageHt = p->PageHt;
- X ePageWid = p->PageWid;
- X eLMarg = p->LMargP;
- X eRMarg = p->RMargP;
- X eTMarg = p->TMargP;
- X eBMarg = p->BMargP;
- X FPRINTF (psos, "/%s{}%s\n", PROTATE, PDEF);
- X }
- Xelse
- X {
- X ePageHt = p->PageWid;
- X ePageWid = p->PageHt;
- X eLMarg = p->LMargL;
- X eRMarg = p->RMargL;
- X eTMarg = p->TMargL;
- X eBMarg = p->BMargL;
- X FPRINTF (psos, "/%s/%s %s %s\n",
- X PROTATE, (90 == p->LandRot) ? PROTPOS : PROTNEG, PLOAD, PDEF);
- X }
- Xif (eTMarg + p->HeadHt > ePageHt)
- X malf1 (eBigHd, p->TMargP + p->HeadHt, p->PageHt);
- Xcw = (ePageWid - eLMarg - eRMarg - (pp->pgCols - 1) * p->ColSep) / pp->pgCols;
- Xif (cw <= 0.0) malf1 (eColWid, cw);
- XputDim (LMARGIN, eLMarg);
- XputDim (RMARGIN, eRMarg);
- XputDim (BMARGIN, eBMarg);
- XputDim (TMARGIN, eTMarg);
- XputDim (PPAGEWD, ePageWid);
- XputDim (PPAGEHT, ePageHt);
- XFPRINTF (psos, "/%s %u %s\n", PPAGEN, pn, PDEF);
- XFPRINTF (psos, "/%s(- %u / %u -)%s\n", PPAGES, pn, tp, PDEF);
- XputDim (FOLDIND, p->FoldInd);
- XputDim (TOPSKIP, p->TSkip);
- XputDim (PDX, cw + p->ColSep);
- XFPRINTF (psos, "%s\n", PPAGEB);
- Xwhile (nb--)
- X {
- X c = getc (psts);
- X if (EOF == c)
- X {
- X if (ferror (psts)) malf1 (eRead, pstfn);
- X malf1 (eUEOF, pstfn);
- X }
- X PUTC (c, psos);
- X }
- XFPRINTF (psos, "%s\n%%%%PageTrailer\n", PPAGEE);
- X}
- X
- X/* readenv - process environment variables */
- X
- XPRIVATE void readenv()
- X
- X/* Function:
- X * Execute any commands in the environment.
- X * Algorithm:
- X * Linear search through the environment variables for any matches.
- X * Call cmd() on a match.
- X * Notes:
- X * 1) Ignore CZPATH. It's handled elsewhere.
- X */
- X{
- Xextern cStrT *environ; /* (5V).*/
- XR4 bStrT *ep; /* Steps through environment variables.*/
- XR3 bStrT cp; /* General purpose.*/
- XR2 bStrT cp2; /* General purpose.*/
- XR1 bStrT cp3; /* General purpose.*/
- X byteT cbuf[MLINE + 1]; /* Command buffer.*/
- X
- Xfor (ep = (bStrT *) environ; NULBSTR != (cp = *ep++);)
- X {
- X if ((NULBSTR != (cp3 = prefix (S(ENVPRE), cp))) &&
- X (NULBSTR == prefix (S(CZPATH), cp)))
- X {
- X cp2 = cbuf;
- X for (; (EOS != B(*cp3)) && ('=' != B(*cp3)); ++cp3)
- X {
- X if (cp2 == &cbuf[MLINE]) malf1 (eMLine, ep[-1], MLINE);
- X *cp2++ = B(*cp3);
- X }
- X if (('=' == B(*cp3)) && (EOS != B(cp3[1])))
- X {
- X ++cp3;
- X *cp2 = EOS;
- X cmd (cbuf, cp3, "Environment", 0);
- X }
- X }
- X }
- X}
- X
- X/* readpth - read every command file on the path */
- X
- XPRIVATE void readpth (cfn)
- XR7 bStrT cfn; /* Command file name.*/
- X
- X/* Function:
- X * Read and execute every cz.rc file on the search path.
- X * Copy every cz.ps file to output.
- X * Algorithm:
- X * Starting at the beginning of the path,
- X * and working toward the end, copy each segment into
- X * fnbuf[], append the command file name, and try to open the
- X * file. If the file can be opened, call readrc() on it, then
- X * close it and proceed to the next segment.
- X */
- X{
- XR1 bStrT p1; /* Step through path.*/
- XR2 bStrT p2; /* Step through path.*/
- XR3 streamT f; /* Command file.*/
- XR4 int i; /* Path length.*/
- XR5 int l; /* Length of command file name.*/
- XR6 int m; /* Max path length.*/
- Xextern cStrT getenv(); /* (3).*/
- X byteT fnbuf[MFILE]; /* Buffer for current file name.*/
- X
- Xl = strlen ((cStrT) cfn);
- Xm = MFILE - 1 - l - MAX (strlen (CZSUF), strlen (PSSUF));
- Xp1 = path;
- Xif (DB(D_CMD)) FPRINTF (stderr, "readpth %s\n", cfn);
- Xdo
- X {
- X p2 = bStrChr (p1, PATHSEP);
- X i = ((NULBSTR == p2) ? strlen (p1) : p2 - p1);
- X if ((0 == i) || (i > m)) malf1 (eMPath, m, p1);
- X (void) strncpy ((cStrT) fnbuf, (cStrT) p1, i);
- X p1 = &fnbuf[i];
- X if ('/' != B(p1[-1])) *p1++ = '/';
- X STRCPY ((cStrT) p1, (cStrT) cfn);
- X p1 += l;
- X STRCPY ((cStrT) p1, CZSUF);
- X f = fopen ((cStrT) fnbuf, "r");
- X if (NULSTRM == f)
- X {
- X if (DB(D_CMD)) FPRINTF (stderr, "trying %s...failed\n", fnbuf);
- X }
- X else
- X {
- X if (DB(D_CMD)) FPRINTF (stderr, "trying %s...ok\n", fnbuf);
- X readrc (f, fnbuf);
- X if (fclose (f)) malf0 (eClose, fnbuf);
- X }
- X STRCPY ((cStrT) p1, PSSUF);
- X f = fopen ((cStrT) fnbuf, "r");
- X if (NULSTRM == f)
- X {
- X if (DB(D_CMD)) FPRINTF (stderr, "trying %s...failed\n", fnbuf);
- X }
- X else
- X {
- X if (DB(D_CMD)) FPRINTF (stderr, "trying %s...ok\n", fnbuf);
- X FPRINTF (psos, "%%%%BeginFile: %s\n", fnbuf);
- X mfcopy (f, 0, fnbuf, psos, 1, Out);
- X if (fclose (f)) malf0 (eClose, fnbuf);
- X FPUTS ("%%EndFile\n", psos);
- X }
- X if (NULBSTR != p2) p1 = p2 + 1;
- X }
- Xwhile (NULBSTR != p2);
- X}
- X
- X/* readrc - read one command file */
- X
- XPRIVATE void readrc (f, fn)
- XR4 streamT f; /* File.*/
- XR3 bStrT fn; /* File name.*/
- X
- X/* Function:
- X * Read through one command file and execute each command.
- X * Algorithm:
- X * Read each line. Strip comments and trailing white space.
- X * Skip leading white
- X * space. Find command. Put NUL at end of it. Skip white
- X * space. Find value. Call cmd().
- X * Notes:
- X *
- X */
- X{
- XR1 bStrT cp; /* General purpose.*/
- XR2 bStrT cmdp; /* Points to command.*/
- X unsigned ln = 0; /* Current line number.*/
- X byteT lb[MLINE]; /* Input line buffer.*/
- X
- Xwhile (NULBSTR != getlic (lb, MLINE, f, fn, &ln, 1, COMMENT))
- X {
- X for (cp = lb; ' ' == B(*cp); ++cp)
- X ;
- X cmdp = cp++;
- X for (; (EOS != B(*cp)) && (' ' != B(*cp)); ++cp)
- X ;
- X if (EOS != B(*cp))
- X {
- X *cp++ = EOS;
- X for (; ' ' == B(*cp); ++cp)
- X ;
- X if (EOS != B(*cp)) cmd (cmdp, cp, fn, ln);
- X else malf0 (eNoArgL, fn, ln, lb);
- X }
- X }
- X}
- X
- X/* undef - undefine one state-octet pair or one whole state */
- X
- XPRIVATE void undef (ss, os)
- X bStrT ss; /* State as a string.*/
- XR1 bStrT os; /* Octet as a string.*/
- X
- X/* Function:
- X * cz0 starts out configured for ISO 8859/1. For other character
- X * sets, it's sometimes necessary to undefine state-octet pairs.
- X * Algorithm:
- X * Convert state to number. If "octet" is All, zap the whole state.
- X * Otherwise, convert octet to number and zap that entry.
- X * Returns:
- X *
- X * Notes:
- X * 1) Dynamic memory is not freed.
- X */
- X{
- XR2 unsigned o; /* Octet.*/
- XR3 unsigned s; /* State.*/
- XR4 soT *sop1; /* Current soT.*/
- XR5 stateT *sp; /* Points to current stateT.*/
- X
- Xs = mra2u (ss, NULBSTR, FALSE, S("State"), (unsigned) 0, (unsigned) MSTATE,
- X (bStrT *) NULL);
- Xif (bStrEQ (S("All"), os))
- X states[s] = (stateT *) NULL;
- Xelse
- X {
- X o = mra2u (os, NULBSTR, FALSE, "Octet", (unsigned) 0, (unsigned) 255,
- X (bStrT *) NULL);
- X sp = states[s];
- X if (((stateT *) NULL) != sp)
- X {
- X sop1 = ((soT *) sp) + o;
- X sop1->so_ps = NULBSTR;
- X }
- X }
- X}
- X
- X/* main - main function */
- X
- XPUBLIC void main (argc, argv)
- X int argc; /* Number of arguments.*/
- XR2 bStrT *argv; /* Points to array of argument strings.*/
- X
- X/* Function:
- X * Main function.
- X * Algorithm:
- X * If there's a -o option, open the output stream.
- X * Call init(), etc.
- X * Step through command line arguments and call cmd() on them.
- X * Step through files and call cvfile() on each.
- X * Notes:
- X *
- X */
- X
- X{
- XR1 bStrT cp; /* Used in argument decoding.*/
- XR3 filT *fp; /* Steps through fil[].*/
- X
- X++argv;
- Xcp = *argv++;
- Xif ((argc >= 3) && (bStrEQ (S("-o"), cp)))
- X {
- X cp = *argv++;
- X if (PIPECHR != B(*cp))
- X psos = fopen ((cStrT) cp, "w");
- X else if (EOS == B(cp[1]))
- X malf1 (eNoPipe, PIPECHR);
- X else
- X psos = popen ((cStrT) &cp[1], "w");
- X if (NULSTRM == psos) malf1 (eOpen, cp);
- X Out = cp;
- X cp = *argv++;
- X }
- Xinit();
- XheadCom();
- Xipath();
- Xreadpth ("header");
- XFPUTS ("%%EndComments\n", psos);
- XFPRINTF (psos, "/%s/load load def\n/%s/def %s def\n/Version(cz%d.%d)%s\n",
- X PLOAD, PDEF, PLOAD, FRZ_MAJ, FRZ_MIN, PDEF);
- Xreadpth ("prolog-beg");
- Xreadenv();
- Xwhile ((NULBSTR != cp) && ('-' == B(*cp)))
- X {
- X ++cp;
- X if (NULBSTR == *argv) malf1 (eNoArg, cp);
- X else cmd (cp, *argv++, sCLine, 0);
- X cp = *argv++;
- X }
- Xif (NULBSTR != cp) usage();
- Xif (filp == &fil[1]) malf1 (eNoFile);
- Xif (DB(D_JOB)) FPRINTF (stderr, "%d file(s)\n", filp - fil - 1);
- XputFnts();
- Xreadpth ("prolog-end");
- XFPUTS ("%%EndProlog\n", psos);
- Xif (Reverse)
- X {
- X for (fp = filp - 1; fp != fil;)
- X cvfile (fp--);
- X }
- Xelse
- X {
- X for (fp = &fil[1]; fp != filp;)
- X cvfile (fp++);
- X }
- XFPRINTF (psos, "%%%%Trailer\n%%%%Pages: %u\n", totPag);
- XdocFnts();
- Xif (EndCtlD) PUTC (4, psos);
- Xmfflush (psos, Out);
- Xif ((PIPECHR == B(*Out)) ? pclose (psos) : fclose (psos)) malf0 (eClose, Out);
- Xif ((NULCSTR != pstfn) && unlink (pstfn)) malf0 (eUnlink, pstfn);
- Xexit (0);
- X}
- END_OF_FILE
- if test 54952 -ne `wc -c <'cz0.c'`; then
- echo shar: \"'cz0.c'\" unpacked with wrong size!
- fi
- # end of 'cz0.c'
- fi
- echo shar: End of archive 11 \(of 14\).
- cp /dev/null ark11isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-